////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

// Η κλάση "Agora" περιγράφει αντικείμενα αγορών. Η αγορά έχει χρώμα και μπάζες
// με properties "xroma" και "bazes" αντίστοιχα. Το χρώμα είναι ένα μονογράμματο
// string που υποδηλώνει το χρώμα της αγοράς με τον συνήθη τρόπο ([S]pades, [C]lubs,
// [D]iamonds, [H]earts, [N]o trump), ενώ οι μπάζες είναι ένας αριθμός που υποδηλώνει
// το πλήθος των μπαζών της αγοράς, από 6 εως 10 μπάζες.
// Υπάρχει, επίσης, το προαιρετικό property "asoi" που εφόσον είναι true, υποδηλώνει
// τους άσους στην αγορά.

Agora = function(obj) {
	var i;

	for (i in obj) {
		this[i] = obj[i];
	}

}

// Η μέθοδος "setAsoi" θέτει ή αφαιρεί τους άσους από την αγορά και επιστρέφει την αγορά,
// ανάλογα με την παράμετρο που περνάμε και επιστρέφει την αγορά.

Agora.prototype.setAsoi = function(nai) {
	if (nai === undefined) nai = true;

	if (nai) this.asoi = true;
	else delete this.asoi;

	return this;
}

// Η μέθοδος "isAsoi" επιστρέφει true εφόσον έχουν δηλωθεί οι άσοι στην αγορά,
// αλλιώς επιστρέφει false.

Agora.prototype.isAsoi = function() {
	if (!this.hasOwnProperty('asoi')) return false;
	return this.asoi;
}

// Οι αγορές ως strings είναι της μορφής "AXB", όπου "A" είναι [Y]es/[N]o και αφορά
// στους άσους, "X" είναι το χρώμα της αγοράς ([S]pades, [C]lubs, [D]iamonds, [H]earts
// και [N]o trump) και "B" είναι οι μπάζες της αγοράς (6, 7, 8, 9, [T]en). Ακολουθούν
// παραδείγματα:
//
//	NC6	Έξι σπαθιά
//	NH7	Επτά κούπες
//	YN7	Επτά άχροα και οι άσοι
//	YH6	Έξι κούπες και οι άσοι
//	NDT	Δέκα καρά
//	YNT	Δέκα άχροα και οι άσοι

// Η μέθοδος "string2agora δέχεται ένα string αγοράς και θέτει ανάλογα τα properties
// τής ανά χείρας αγοράς.

Agora.prototype.string2agora = function(s) {
	if (s.substr(0, 1) == 'Y') this.setAsoi();
	else if (s.substr(0, 1) == 'N') this.setAsoi(false);
	else globals.fatal('Agora.string2agora: ' + s + ': απροσδιόριστοι άσοι στην αγορά');

	this.xroma = s.substr(1, 1);
	if (!Agora.xroma.hasOwnProperty(this.xroma)) globals.fatal('Agora.string2agora: ' + s + ': λάθος χρώμα αγοράς');

	this.bazes = s.substr(2, 1);
	if (!Agora.sezab.hasOwnProperty(this.bazes)) globals.fatal('Agora.string2agora: ' + s + ': λάθος μπάζες αγοράς');
	this.bazes = Agora.sezab[this.bazes];

	return this;
}

// Η μέθοδος "agora2string" επιστρέφει την ανά χείρας αγορά ως string αγοράς, σύμφωνα
// με τους κανόνες τής αντίστροφης μεθόδου "string2agora".

Agora.prototype.agora2string = function() {
	var s = this.isAsoi() ? 'Y' : 'N';

	if (Agora.xroma.hasOwnProperty(this.xroma)) s += this.xroma;
	else globals.fatal('Agora.agora2string: λάθος χρώμα αγοράς');

	if (Agora.bazes.hasOwnProperty(this.bazes)) s += Agora.bazes[this.bazes];
	else globals.fatal('Agora.agora2string: λάθος μπάζες αγοράς');

	return s;
}

// Η μέθοδος "axia" επιστρέφει την αξία τής αγοράς, δηλαδή πόσα καπίκια αποτιμάται
// η κάθε μπάζα, ανάλογα με την αγορά.

Agora.prototype.axia = function() {
	if (!Agora.xroma.hasOwnProperty(this.xroma)) globals.fatal('Agora.axia: λάθος χρώμα αγοράς');
	if (!Agora.bazes.hasOwnProperty(this.bazes)) globals.fatal('Agora.axia: λάθος μπάζες αγοράς');

	// Για τις αγορές των έξι μπαζών οι αξίες αναφέρονται στον πίνακα
	// των χρωμάτων.

	if (this.bazes == 6) return Agora.xroma[this.xroma];

	// Για αγορές μεγαλύτερες των έξι μπαζών, η αξία της αγοράς ισούται
	// με το πλήθος των μπαζών, εκτός και αν πρόκειται για άχροα οπότε
	// η αξία προσαυξάνεται κατά ένα επιπλέον καπίκι. Σε κάθε περίπτωση
	// η αξία της αγοράς δεν μπορεί να υπερβαίνει τα δέκα καπίκια.

	if (this.xroma != 'N') return this.bazes;

	// Είμαστε σε άχροα, οπότε θα πρέπει να αυξήσουμε κατά ένα καπίκι
	// για αγορές από επτά έως εννέα μπάζες.

	return this.bazes < 10 ? this.bazes + 1 : this.bazes;
}

Agora.prototype.lektiko = function() {
	var s = '';

	switch (this.bazes) {
	case 6:	s = 'ΕΞΙ'; break;
	case 7:	s = 'ΕΠΤΑ'; break;
	case 8:	s = 'ΟΚΤΩ'; break;
	case 9:	s = 'ΕΝΝΙΑ'; break;
	case 10: s = 'ΔΕΚΑ'; break;
	default: globals.fatal('Agora.lektiko: ' + this.bazes + ': ακαθόριστες μπάζες αγοράς');
	}

	s += ' ';
	switch (this.xroma) {
	case 'S': s += 'ΜΠΑΣΤΟΥΝΙΑ'; break;
	case 'C': s += 'ΣΠΑΘΙΑ'; break;
	case 'D': s += 'ΚΑΡΑ'; break;
	case 'H': s += 'ΚΟΥΠΕΣ'; break;
	case 'N': s += 'ΑΧΡΟΑ'; break;
	default: globals.fatal('Agora.lektiko: ' + this.xroma + ': ακαθόριστο χρώμα αγοράς');
	}

	if (this.isAsoi()) s += ' και οι ΑΣΟΙ';
	return s;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

// Η λίστα "xroma" περιέχει τα αποδεκτά χρώματα των αγορών: [S]spades, [C]lubs,
// [D]iamonds, [H]earts και [N]o trump. Ως τιμές δίνονται οι αξίες των αγορών
// για τις έξι μπάζες.

Agora.xroma = {
	'S': 2,
	'C': 3,
	'D': 4,
	'H': 5,
	'N': 6,
};

// Το array "amorx" περιέχει τα χρώματα των αγορών κατά σειρά δυναμικότητας
// αγοράς.

Agora.amorx = [
	'S',
	'C',
	'D',
	'H',
	'N',
];

// Η λίστα "sezab" περιέχει τα αποδεκτά πλήθη μπαζών για τις αγορές. Πρόκειται
// για μονογράμματα strings με τιμές τα αντίστοιχα πλήθη μπαζών. Παρέχεται και
// η αντίστροφη λίστα "bazes" δεικτοδοτημένη με το πλήθος των μπαζών.

Agora.sezab = {
	'6': 6,
	'7': 7,
	'8': 8,
	'9': 9,
	'T': 10,
}
Agora.bazes = {};

;(function() {
	var i;

	for (i in Agora.sezab) {
		Agora.bazes[Agora.sezab[i]] = i;
	}
})();

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

// Η κλάση "Dilosi" απεικονίζει δηλώσεις κατά την πλειοδοσία τής αγοράς.
// Οι δηλώσεις έχουν τα εξής properties:
//
//	xroma	Το χρώμα της δήλωσης.
//
//	bazes	Το πλήθος μπαζών της δήλωσης.
//
//	paso	Αν υπάρχει και είναι true υποδηλώνει δήλωση "ΠΑΣΟ".
//
//	grafio	Αν υπάρχει και είναι true υποδηλώνει δήλωση "ΑΜΑ ΜΕΙΝΟΥΝ".
//
//	edo	Αν υπάρχει είναι δήλωση "ΕΧΩ".
//
// Στις δηλώσεις "ΠΑΣΟ" τα properties "xroma" και "bazes" πρέπει να είναι
// καθορισμένα και δείχνουν το σημείο της αγοράς στο οποίο δηλώθηκε το
// "ΠΑΣΟ", εκτός και αν δεν έχει προηγηθεί καμία δήλωση αγοράς οπότε
// πρέπει να είναι καθορισμένο το property "grafio".

Dilosi = function(obj) {
	var i;
	for (i in obj) this[i] = obj[i];
}

Dilosi.prototype.setPaso = function() {
	this.paso = 1;
	return this;
}

Dilosi.prototype.setEdo = function() {
	this.edo = 1;
	return this;
}

Dilosi.prototype.isPaso = function() {
	if (!this.hasOwnProperty('paso')) return false;
	return this.paso;
}

Dilosi.prototype.oxiPaso = function() {
	return !this.isPaso();
}

Dilosi.prototype.isGrafio = function() {
	if (!this.hasOwnProperty('grafio')) return false;
	return this.grafio;
}

Dilosi.prototype.oxiGrafio = function() {
	return !this.isGrafio();
}

Dilosi.prototype.isEdo = function() {
	if (!this.hasOwnProperty('edo')) return false;
	return this.edo;
}

Dilosi.prototype.oxiEdo = function() {
	return !this.isEdo();
}

Dilosi.prototype.setProta = function() {
	delete this.paso;
	delete this.grafio;
	delete this.edo;
	this.xroma = 'S';
	this.bazes = 6;
	return this;
}

Dilosi.prototype.isProta = function() {
	if (this.xroma != 'S') return false;
	if (this.bazes != 6) return false;
	return true;
}

// Οι δηλώσεις ως strings είναι της μορφής "DXB", όπου "X" είναι το χρώμα
// της αγοράς και "B" είναι οι μπάζες της αγοράς.
//
// Οι δηλώσεις "ΠΑΣΟ" είναι της μορφής "PXB", όπου "X" και "B" είναι το χρώμα
// και το πλήθος μπαζών στο σημείο που δηλώθηκε πάσο. Αν δεν έχει προηγηθεί
// καμία άλλη δήλωση αγοράς, τότε το "ΠΑΣΟ" είναι της μορφής "PTG". Ο κωδικός
// "TG" οφείλει την ονομασία του στην έκφραση "ΤΑ ΓΡΑΦΩ" που είναι ταυτόσημη
// με το "ΑΜΑ ΜΕΙΝΟΥΝ".
//
// Τέλος, υπάρχουν οι δηλώσεις "DTG" που υποδηλώνουν "ΑΜΑ ΜΕΙΝΟΥΝ".

Dilosi.prototype.string2dilosi = function(s) {
	var pde;

	delete this.paso;
	delete this.grafio;
	delete this.edo;
	delete this.xroma;
	delete this.bazes;

	if (s.match(/^DTG/)) {
		this.grafio = 1;
		return this;
	}

	if (s.match(/^PTG/)) {
		this.paso = 1;
		this.grafio = 1;
		return this;
	}

	if ((pde = s.substr(0, 1)) == 'P') this.paso = 1;
	else if (pde == 'E') this.edo = 1;
	else if (pde != 'D') globals.fatal(s + ': λάθος είδος δήλωσης');

	this.xroma = s.substr(1, 1);
	if (!Agora.xroma.hasOwnProperty(this.xroma)) globals.fatal(this.xroma + ': λάθος χρώμα δήλωσης');

	this.bazes = s.substr(2, 1);
	if (!Agora.sezab.hasOwnProperty(this.bazes)) globals.fatal(this.bazes + ': λάθος μπάζες δήλωσης');
	this.bazes = Agora.sezab[this.bazes];

	return this;
}

// Η μέθοδος "dilosi2string" επιστρέφει τη δήλωση ως string σύμφωνα με τους
// κανόνες τής αντίστροφης μεθόδου "string2dilosi".

Dilosi.prototype.dilosi2string = function() {
	var pde;

	if (this.isGrafio()) return this.isPaso() ? 'PTG' : 'DTG';
	if (!Agora.xroma.hasOwnProperty(this.xroma)) globals.fatal(this.xroma + ': λάθος χρώμα δήλωσης');
	if (!Agora.bazes.hasOwnProperty(this.bazes)) globals.fatal(this.bazes + ': λάθος μπάζες δήλωσης');
	if (this.isPaso()) pde = 'P';
	else if (this.isEdo()) pde = 'E';
	else pde = 'D';
	return pde + this.xroma + Agora.bazes[this.bazes];
}

// Η μέθοδος "epomeni" επιστρέφει την επόμενη δήλωση της ανά χείρας δηλώσεως.
// Εαν η ανά χείρας δήλωση είναι δήλωση "ΠΑΣΟ", τότε επιστρέφεται δήλωση του
// ιδίου ύψους, αλλιώς επιστρέφεται η αμέσως επόμενη δήλωση. Ακολουθούν
// παραδείγματα:
//
//	DH6	DN6	δήλωση "έξι κούπες", επόμενη "έξι άχροα"
//	DC7	DD7	δήλωση "επτά σπαθιά", επόμενη "επτά καρά"
//	DN7	DS8	δήλωση "επτά άχροα", επόμενη "οκτώ μπαστούνια"
//	ED7	DH7	δήλωση "έχω επτά καρά", επόμενη "επτά κούπες"
//	PH6	DH6	δήλωση "πάσο στις έξι κούπες", επόμενη "έξι κούπες"
//	DTG	DS6	δήλωση "άμα μείνουν", επόμενη "έξι μπαστούνια"
//	EN6	DS7	δήλωση "έχω άχροα", επόμενη "επτά μπαστούνια"
//	PTG	DTG	δήλωση "πάσο στο άμα μείνουν", επόμενη "άμα μείνουν"

Dilosi.prototype.epomeniDilosi = function() {
	if (this.isPaso()) {
		if (this.isGrafio()) return new Dilosi({
			grafio: 1,
		});

		return new Dilosi({
			xroma: this.xroma,
			bazes: this.bazes,
		});
	}

	if (this.isGrafio()) return new Dilosi({
		xroma: 'S',
		bazes: 6,
	});

	if (this.xroma != 'N') return new Dilosi({
		xroma: this.xroma.epomenoXroma(),
		bazes: this.bazes,
	});

	if (this.bazes < 10) return new Dilosi({
		xroma: 'S',
		bazes: this.bazes + 1,
	});

	if (this.oxiEdo()) return new Dilosi({
		xroma: 'N',
		bazes: 10,
	});

	globals.fatal('Dilosi.epomeni: δεν υπάρχει επόμενη δήλωση');
}

// Η μέθοδος "iparxiEpomeni" επιστρέφει true εφόσον η ανά χείρας δήλωση
// δεν είναι η μέγιστη δυνατή, η οποία είναι "ΕΧΩ ΔΕΚΑ ΑΧΡΟΑ".

Dilosi.prototype.iparxiEpomeni = function() {
	if (this.bazes < 10) return true;
	if (this.xroma != 'N') return true;
	return this.oxiEdo();
}

Dilosi.prototype.lektiko = function() {
	var s = '';

	if (this.isGrafio()) return 'ΑΜΑ ΜΕΙΝΟΥΝ';

	if (this.isEdo()) s += 'ΕΧΩ ';

	switch (this.bazes) {
	case 6:	s += 'ΕΞΙ'; break;
	case 7:	s += 'ΕΠΤΑ'; break;
	case 8:	s += 'ΟΚΤΩ'; break;
	case 9:	s += 'ΕΝΝΙΑ'; break;
	case 10: s += 'ΔΕΚΑ'; break;
	default: globals.fatal('Dilosi.lektiko: ' + this.bazes + ': ακαθόριστες μπάζες δήλωσης');
	}

	s += ' ';
	switch (this.xroma) {
	case 'S': s += 'ΜΠΑΣΤΟΥΝΙΑ'; break;
	case 'C': s += 'ΣΠΑΘΙΑ'; break;
	case 'D': s += 'ΚΑΡΑ'; break;
	case 'H': s += 'ΚΟΥΠΕΣ'; break;
	case 'N': s += 'ΑΧΡΟΑ'; break;
	default: globals.fatal('Dilosi.lektiko: ' + this.xroma + ': ακαθόριστο χρώμα δήλωσης');
	}

	return s;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

Simetoxi = function(obj) {
	var i;
	for (i in obj) this[i] = obj[i];
}

Simetoxi.prototype.setPaso = function() {
	this.simetoxi = 'ΠΑΣΟ';
}

Simetoxi.prototype.isPaso = function() {
	return(this.simetoxi == 'ΠΑΣΟ');
}

Simetoxi.prototype.oxiPaso = function() {
	return !this.isPaso();
}

Simetoxi.prototype.setPezo = function() {
	this.simetoxi = 'ΠΑΙΖΩ';
}

Simetoxi.prototype.isPezo = function() {
	return(this.simetoxi == 'ΠΑΙΖΩ');
}

Simetoxi.prototype.setMonos = function() {
	this.simetoxi = 'ΜΟΝΟΣ';
}

Simetoxi.prototype.isMonos = function() {
	return(this.simetoxi == 'ΜΟΝΟΣ');
}

Simetoxi.prototype.setMazi = function() {
	this.simetoxi = 'ΜΑΖΙ';
}

Simetoxi.prototype.isMazi = function() {
	return(this.simetoxi == 'ΜΑΖΙ');
}

Simetoxi.prototype.setVoithao = function() {
	this.simetoxi = 'ΒΟΗΘΑΩ';
}

Simetoxi.prototype.isVoithao = function() {
	return(this.simetoxi == 'ΒΟΗΘΑΩ');
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

// Η μέθοδος που ακολουθεί είναι πολύ σημαντική και σκοπό έχει τον καθορισμό
// τού επόμενου παίκτη, δηλαδή τού παίκτη που θα πρέπει να κάνει την επόμενη
// ενέργεια στο παιχνίδι. Παράλληλα, καθορίζεται και η τρέχουσα φάση τού
// παιχνιδιού.
// Όλα αυτά δεν επιτελούνται από την μέθοδο "setEpomenos" αυτήν καθαυτήν, αλλά
// από επιμέρους μεθόδους, ανάλογα με τη φάση τού παιχνιδιού.

Trapezi.prototype.setEpomenos = function() {
	if (!this.hasOwnProperty('epomenos')) globals.fatal('Trapezi.setEpomenos: ακαθόριστος τρέχων παίκτης');
	switch (this.fasi) {
	case 'ΔΙΑΝΟΜΗ': return this.setEpomenosDianomi();
	case 'ΔΗΛΩΣΗ': return this.setEpomenosDilosi();
	case 'ΑΛΛΑΓΗ': return this.setEpomenosAlagi();
	case 'ΣΟΛΟ': return this.setEpomenosSolo();
	case 'ΑΓΟΡΑ': return this.setEpomenosAgora();
	case 'ΣΥΜΜΕΤΟΧΗ1': return this.setEpomenosSimetoxi1();
	case 'ΣΥΜΜΕΤΟΧΗ2': return this.setEpomenosSimetoxi2();
	case 'ΣΥΜΜΕΤΟΧΗ3': return this.setEpomenosSimetoxi3();
	default: globals.fatal('Trapezi.setEpomenos: ' + this.fasi + ': απρόβλεπτη φάση');
	}
}

// Είμαστε σε φάση διανομής, επομένως θα πρέπει να περάσουμε σε φάση δηλώσεων
// πλειοδοσίας αγοράς και ο παίκτης που θα μιλήσει πρώτος θα είναι ο παίκτης
// μετά τον dealer.

Trapezi.prototype.setEpomenosDianomi = function() {
	this.fasi = 'ΔΗΛΩΣΗ';
	this.dilosi = {};
	this.dilosiCount = 0;
	this.paso = {};
	this.epomenos = this.dealer.epomenosPektis();
	return this;
}

// Είμαστε σε φάση δηλώσεων πλειοδοσίας αγοράς και θα πρέπει να βρούμε ποιος
// παίκτης έχει σειρά να κάνει την επόμενη δήλωση.

Trapezi.prototype.setEpomenosDilosi = function() {
	var proin = this.epomenos;

	// Θα διατρέξουμε τους παίκτες με σκοπό να βρούμε τον επόμενο
	// που έχει σειρά να μιλήσει.

	while (true) {
		// Δοκιμάζουμε τον επόμενο από τον τρέχοντα ενεργό παίκτη.

		this.epomenos = this.epomenos.epomenosPektis();

		// Αν κλείσαμε κύκλο, σπάμε τον κύκλο των δοκιμών.

		if (this.epomenos == proin) break;

		// Αν ο παίκτης που έχουμε ως υποψήφιο ενεργό παίκτη έχει
		// δηλώσει πάσο, προχωρούμε στον επόμενο παίκτη.

		if (this.paso.hasOwnProperty(this.epomenos)) continue;

		// Αν ο υποψήφιος ενεργός παίκτης είναι ο υποψήφιος τζογαδόρος,
		// τότε πάλι έχουμε κλείσει κάποιο είδος κύκλου.

		if (this.epomenos == this.tzogadoros) break;

		// Ο υποψήφιος ενεργός παίκτης έχει όλα τα εχέγγυα να κάνει
		// την επόμενη δήλωση.

		return this;
	}

	// Έχει σπάσει ο κύκλος δοκιμών για τον εντοπισμό του επόμενου παίκτη
	// που έχει σειρά να μιλήσει, επομένως σημαίνει ότι κλείσαμε κύκλο.
	// Αν υπάρχει κάποιος υποψήφιος τζογαδόρος, καθίσταται τζογαδόρος.

	if (this.tzogadoros) {
		this.setTzogadoros();
		return this;
	}

	// Δεν υπάρχει υποψήφιος τζογαδόρος, επομένως όλοι οι παίκτες δήλωσαν
	// "ΠΑΣΟ". Αν το τραπέζι μας παίζει το πάσο προχωρούμε στην εκτέλεση.

	if (this.isPaso()) {
		this.fasi = 'ΕΚΤΕΛΕΣΗ';
		this.epomenos = this.dealer.epomenosPektis();
		return this;
	}

	// Όλοι οι παίκτες δήλωσαν "ΠΑΣΟ" και το τραπέζι δεν παίζει το πάσο.
	// Σ' αυτή την περίπτωση προχωρούμε στο άνοιγμα του τζόγου, ενέργεια
	// την οποία θα εκτελέσει ο dealer.

	this.fasi = 'FLOP';
	this.epomenos = this.dealer.epomenosPektis();
	return this;
}

Trapezi.prototype.setEpomenosAlagi = function() {
	if (!this.hasOwnProperty('tzogadoros')) globals.fatal('Ακαθόριστος τζογαδόρος');
	this.epomenos = this.tzogadoros;
	return this;
}

Trapezi.prototype.setEpomenosSolo = function() {
	this.epomenos = this.dealer.epomenosPektis();
	return this;
}

Trapezi.prototype.setEpomenosAgora = function() {
	this.epomenos = this.tzogadoros.epomenosPektis();
	this.fasi = 'ΣΥΜΜΕΤΟΧΗ1';
	this.simetoxi = {};
	this.paso = {};
	this.bazes = {};
	return this;
}

// Η φάση "ΣΥΜΜΕΤΟΧΗ1" είναι η φάση κατά την οποία ο πρώτος παίκτης
// μετά τον τζογαδόρο δηλώνει για πρώτη φορά αν θα παίξει ή όχι.

Trapezi.prototype.setEpomenosSimetoxi1 = function() {
	this.epomenos = this.epomenos.epomenosPektis();
	if (this.epomenos == this.tzogadoros) this.epomenos = this.epomenosPektis();
	this.fasi = 'ΣΥΜΜΕΤΟΧΗ2';
	return this;
}

// Η φάση "ΣΥΜΜΕΤΟΧΗ2" είναι η φάση κατά την οποία ο δεύτερος αμυνόμενος
// δηλώνει αν και με ποιο τρόπο θα διεκδικήσει ή όχι τις μπάζες που του
// αναλογούν.

Trapezi.prototype.setEpomenosSimetoxi2 = function() {
	var pektis1, pektis2;

	pektis1 = this.tzogadoros.epomenosPektis();
	pektis2 = pektis1.epomenosPektis();

	// Εξετάζουμε πρώτα την περίπτωση κατά την οποία ο πρώτος παίκτης
	// έχει δηλώσει "ΠΑΙΖΩ".

	if (this.simetoxi[pektis1].isPezo()) {
		// Αν και ο δεύτερος παίκτης δήλωσε "ΠΑΙΖΩ", τότε προχωρούμε
		// στην εκτέλεση της αγοράς.

		if (this.simetoxi[pektis2].isPezo()) {
			this.fasi = 'ΕΚΤΕΛΕΣΗ';
			this.epomenos = this.dealer.epomenosPektis();
			return this;
		}

		// Ο δεύτερος παίκτης δήλωσε "ΠΑΣΟ", επομένως ο πρώτος έχει
		// δικαίωμα να ξαναμιλήσει.

		this.fasi = 'ΣΥΜΜΕΤΟΧΗ3';
		this.epomenos = pektis1;
		return this;
	}

	// Ο πρώτος παίκτης έχει δηλώσει "ΠΑΣΟ".

	if (this.simetoxi[pektis2].isMazi()) {
		this.simetoxi[pektis1].setVoithao();
		this.fasi = 'ΕΚΤΕΛΕΣΗ';
		this.epomenos = this.dealer.epomenosPektis();
		return this;
	}

	if (this.simetoxi[pektis2].isPaso()) {
		this.bazes[this.tzogadoros] = 10;
		this.fasi = 'ΠΛΗΡΩΜΗ';
		this.epomenos = this.dealer.epomenosPektis();
		return this;
	}

	// Ο δεύτερος παίκτης δήλωσε "ΠΑΙΖΩ" ενώ ο πρώτος έχει δηλώσει
	// "ΠΑΣΟ", επομένως ο πρώτος παίκτης έχει δικαίωμα να ξαναμιλήσει.

	this.fasi = 'ΣΥΜΜΕΤΟΧΗ3';
	this.epomenos = pektis1;
	return this;
}

// Η φάση "ΣΥΜΜΕΤΟΧΗ3" είναι η φάση του παιχνιδιού στην οποία ο πρώτος
// αμυνόμενος έχει τη δυνατότητα να δηλώσει εκ νέου αν και με ποιον
// τρόπο θα διεκδικήσει τις μπάζες που του αναλογούν.

Trapezi.prototype.setEpomenosSimetoxi3 = function() {
	var pektis1, pektis2;

	pektis1 = this.tzogadoros.epomenosPektis();
	pektis2 = pektis1.epomenosPektis();

	// Εξετάζουμε πρώτα την περίπτωση κατά την οποία ο δεύτερος παίκτης
	// έχει δηλώσει "ΠΑΣΟ".

	if (this.simetoxi[pektis2].isPaso()) {
		if (this.simetoxi[pektis1].isMazi()) {
			this.simetoxi[pektis2].setVoithao();
			this.fasi = 'ΕΚΤΕΛΕΣΗ';
			this.epomenos = this.dealer.epomenosPektis();
			return this;
		}

		this.setEpomenosSimetoxiEktelesi();
		return this;
	}

	// Ο δεύτερος παίκτης έχει δηλώσει "ΠΑΙΖΩ", ενώ ο πρώτος είχε
	// δηλώσει "ΠΑΣΟ" και εξετάζουμε τώρα τη δεύτερη δήλωση τού
	// πρώτου παίκτη.

	if (this.simetoxi[pektis1].isMazi()) {
		this.fasi = 'ΕΚΤΕΛΕΣΗ';
		this.epomenos = this.dealer.epomenosPektis();
		return this;
	}

	// Ο πρώτος παίκτης δήλωσε "ΠΑΣΟ" για δεύτερη φορά.

	this.setEpomenosSimetoxiEktelesi();
	return this;
}

// Μετά τις δηλώσεις συμμετοχής καταλήξαμε σε εκτέλεση της αγοράς είτε με έναν, είτε
// με δύο αμυνόμενους παίκτες, και ψάχνουμε τον παίκτη που έχει σειρά να παίξει.

Trapezi.prototype.setEpomenosSimetoxiEktelesi = function() {
	this.fasi = 'ΕΚΤΕΛΕΣΗ';
	this.epomenos = this.dealer.epomenosPektis();

	// Αν δεν υπάρχει δήλωση συμμετοχής, τότε πρόκειται για τον τζογαδόρο.

	if (!this.simetoxi.hasOwnProperty(this.epomenos)) return this;

	// Αν η δήλωση συμμετοχής του υποψήφιου επόμενου παίκτη δεν είναι "ΠΑΣΟ",
	// τότε αυτός είναι πράγματι ο επόμενος παίκτης.

	if (this.simetoxi[this.epomenos].oxiPaso()) return this;

	// Η μόνη περίπτωση που απομένει είναι ο άλλος παίκτης.

	this.epomenos = this.epomenos.epomenosPektis();
	return this;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

// Στο τραπέζι προστίθενται διάφορα properties που έχουν να κάνουν με την
// εξέλιξη του παιχνιδιού.
//
//	dealer		Είναι η θέση του παίκτη που μοίρασε.
//
//	fasi		Σε ποιά φάση βρίσκεται το παιχνίδι την τρέχουσα
//			χρονική στιγμή, π.χ. "ΔΗΛΩΣΗ", "ΑΓΟΡΑ", "ΣΥΜΜΕΤΟΧΗ" κλπ.
//
//	epomenos	Είναι η θέση του παίκτη που έχει σειρά να κάνει την επόμενη
//			ενέργεια.
//
//	dilosiCount	Το συνολικό πλήθος των δηλώσεων της πλειοδοσίας τής αγοράς.
//
//	tzogadoros	Είναι η θέση του παίκτη που κέρδισε την αγορά, εφόσον έγινε
//			αγορά. Κατά τη διάρκεια τής πλειοδοσίας τής αγοράς είναι
//			η θέση τού τελευταίου παίκτη που έκανε δήλωση αγοράς.
//
//	agora		Είναι η αγορά ως χρώμα, αριθμό μπαζών και άσους. Κατά τη
//			διάρκεια τής πλειοδοσίας τής αγοράς είναι η τελευταία δήλωση
//			αγοράς.
//
//	tzogos		Είναι τα φύλλα τού τζόγου ως χαρτωσιά. Μετά την αλλαγή είναι
//			τα σκάρτα ως χαρτωσιά.
//
// Τα properties που ακολουθούν είναι λίστες δεικτοδοτημένες με τη θέση τού παίκτη.
//
//	fila		Τα φύλλα του κάθε παίκτη ως χαρτωσιές.
//
//	dilosi		Οι τελευταίες δηλώσεις των παικτών.
//
//	paso		Οι δηλώσεις "ΠΑΣΟ" κατά την πλειοδοσία της αγοράς.
//
//	simetoxi	Οι δηλώσεις συμμετοχής.

Trapezi.prototype.pexnidiCleanup = function() {
	delete this.dealer;
	delete this.epomenos;
	delete this.dilosiCount;
	delete this.tzogadoros;
	delete this.ekinisi;
	delete this.agora;
	delete this.tzogos;

	delete this.fila;
	delete this.dilosi;
	delete this.paso;
	delete this.simetoxi;

	delete this.bazes;

	return this;
}

// Ακολουθεί λίστα μεθόδων εφαρμογής συνεπειών ενέργειας κατά είδος ενέργειας. Αυτές
// οι μέθοδοι εφαρμόζονται στο τραπέζι αμέσως μετά την εισαγωγή τής ενέργειας ως
// τελευταίας ενέργειας στην τελευταία διανομή τού τραπεζιού.

Trapezi.energiaAddMap = {
	// Η ενέργεια τύπου "ΔΙΑΝΟΜΗ" είναι πάντα η πρώτη ενέργεια κάθε διανομής και αφορά
	// ουσιαστικά το μοίρασμα. Τα data της ενέργειας είναι η τράπουλα ανακατωμένη ως ένα
	// ενιαίο string, όπου οι πρώτοι 20 χαρακτήρες είναι τα φύλλα του πρώτου παίκτη, οι
	// επόμενοι 20 χαρακτήρες είναι τα φύλλα τού δεύτερου παίκτη, οι επόμενοι 20 χαρακτήρες
	// είναι τα φύλλα τού τρίτου παίκτη και οι 4 χαρακτήρες που περισσεύουν είναι τα φύλλα
	// του τζόγου.

	'ΔΙΑΝΟΜΗ': function(energia) {
		var thesi;

		// Η διανομή είναι το κατάλληλο σημείο να καθαρίσουμε όλα τα properties που
		// αφορούν στην αγορά και στην εκτέλεση τού παιχνιδιού.

		this.pexnidiCleanup();
		this.fasi = 'ΔΙΑΝΟΜΗ';
		this.dealer = energia.pektis;
		this.fila = {};
		for (thesi in Prefadoros.thesiValid) {
			this.fila[thesi] = energia.data.substr((thesi - 1) * 20, 20).toXartosia();
		}
		this.tzogos = energia.data.substr(60, 4).toXartosia();

		// Σε κάθε φάση πρέπει να υπάρχει ο τρέχων ενεργός παίκτης. Στη φάση
		// τής διανομής αυτός τίθεται με το χέρι και είναι ο ίδιος ο dealer.

		this.epomenos = this.dealer;

		return this;
	},

	// Οι ενέργειες τύπου "ΔΗΛΩΣΗ" ακολουθούν την ενέργεια τύπου "ΔΙΑΝΟΜΗ" και αφορούν στις
	// δηλώσεις των παικτών. Με τις δηλώσεις καθορίζεται ο τζογαδόρος. Αν και οι τρεις παίκτες
	// δηλώσουν "ΠΑΣΟ", τότε αν το τραπέζι παίζει το πάσο προχωρούμε στην εκτέλεση με τις
	// πολλές, αλλιώς 

	'ΔΗΛΩΣΗ': function(energia) {
		var pektis, dilosi, thesi, data;

		pektis = energia.pektis;
		data = energia.data.split(':');
		dilosi = (new Dilosi()).string2dilosi(data[0]);
		if (data.length == 2) this.tzogos = data[1].toXartosia();

		this.dilosiCount++;

		// Αν έχουμε δήλωση "ΠΑΣΟ" δεν υπάρχουν προβλήματα.

		if (dilosi.isPaso()) {
			this.paso[pektis] = true;
			return this;
		}

		// Η δήλωση είναι δήλωση αγοράς, οπότε σημαίνει ότι ο παίκτης
		// διεκδικεί την αγορά και συνεπώς είναι υποψήφιος τζογαδόρος.

		this.dilosi[pektis] = dilosi;
		this.tzogadoros = pektis;
		this.agora = dilosi;

		// Αν υπάρχει δήλωση "ΑΜΑ ΜΕΙΝΟΥΝ" από κάποιον άλλον παίκτη,
		// θα πρέπει ο παίκτης αυτός να τεθεί σε κατάσταση "ΠΑΣΟ".

		for (thesi in Prefadoros.thesiValid) {
			if (thesi == pektis) continue;
			if (this.paso[thesi]) continue;
			if (!this.dilosi[thesi]) continue;
			if (this.dilosi[thesi].oxiGrafio()) continue;

			// Εντοπίσαμε άλλον παίκτη που είχε δήλωση
			// "ΑΜΑ ΜΕΙΝΟΥΝ".

			this.paso[thesi] = true;
		}

		// Αν δεν έχουμε αγγίξει τη μέγιστη δυνατή δήλωση αγοράς, τότε
		// δεν έχουμε πρόβλημα και συνεχίζουμε την όποια διαδικασία.

		if (dilosi.iparxiEpomeni()) return this;

		// Έχουμε αγγίξει τη μέγιστη δυνατή δήλωση αγοράς, ήτοι "ΕΧΩ ΔΕΚΑ
		// ΑΧΡΟΑ". Σ' αυτή την περίπτωση θα πρέπει να θέσουμε σε κατάσταση
		// "ΠΑΣΟ" τυχόν άλλους διεκδικητές της αγοράς.

		for (thesi in Prefadoros.thesiValid) {
			if (thesi == pektis) continue;
			if (this.paso[thesi]) continue;
			if (!this.dilosi[thesi]) continue;

			// Εντοπίσαμε άλλον παίκτη που διεκδικούσε
			// την αγορά.

			this.paso[thesi] = true;
		}

		// Δεν μπορούν να γίνουν άλλες δηλώσεις αγοράς, επομένως ο παίκτης
		// καθίσταται τζογαδόρος και περνάμε σε φάση αλλαγής.

		this.setTzogadoros();
		return this;
	},

	'ΣΟΛΟ': function(energia) {
		this.fasi = 'ΣΟΛΟ';
		this.ekinisi = (new Agora()).string2agora(energia.data);
		return this;
	},

	// Τα δεδομένα της ενέργειας αγοράς περιέχουν την αγορά, τα φύλλα τού τζογαδόρου
	// και τα σκάρτα. Ως διαχωριστής χρησιμοποιείται το ":", ενώ τα φύλλα του τζογαδόρου
	// και τα σκάρτα δεν καθορίζονται όταν η ενέργεια απευθύνεται στους αντιπάλους.

	'ΑΓΟΡΑ': function(energia) {
		var data, skarta, i;

		data = energia.data.split(':');
		this.fasi = 'ΑΓΟΡΑ';
		this.agora = (new Agora()).string2agora(data[0]);

		if (data.length < 2) return this;
		if (data.length != 2) globals.fatal(energia.data + ': λανθασμένα δεδομένα ενέργειας αγοράς');

		skarta = data[1].toXartosia();
		for (i in skarta.fila) this.fila[this.tzogadoros].delf(skarta.fila[i]);
		this.skarta = skarta;

		return this;
	},

	// Τα δεδομένα της ενέργειας συμμετοχής δεν είναι τίποτε άλλο από την ίδια τη δήλωση
	// συμμετοχής, δηλαδή μια από τις δηλώσεις "ΠΑΙΖΩ", "ΠΑΣΟ", "ΜΑΖΙ".

	'ΣΥΜΜΕΤΟΧΗ': function(energia) {
		this.simetoxi[this.epomenos] = new Simetoxi({
			simetoxi: energia.data,
		});
		return this;
	},

	'ΠΛΗΡΩΜΗ': function(energia) {
		console.log('>>>>>>>>>>>>>>>ΠΛΗΡΩΜΗ');
		return this;
	},
};

// Η μέθοδος "dilosiPaso" δέχεται ως παράμετρο μια θέση τού τραπεζιού και επιστρέφει
// true εφόσον ο παίκτης στη συγκεκριμένη θέση δήλωσε πάσο κατά τη φάση της πλειοδοσίας
// τής αγοράς.

Trapezi.prototype.dilosiPaso = function(thesi) {
	if (!this.paso.hasOwnProperty(thesi)) return false;
	if (!this.dilosi.hasOwnProperty(thesi)) return true;
	return this.dilosi[thesi].oxiGrafio();
}

Trapezi.prototype.setTzogadoros = function() {
	this.fila[this.tzogadoros].addXartosia(this.tzogos);
	this.fasi = 'ΑΛΛΑΓΗ';
	this.epomenos = this.tzogadoros;
	return this;
}
